/*            Copyright(c) 2006-2008 Dave Sexton           *
 * http://www.codeplex.com/DocProject                      *
 * http://www.codeplex.com/DocProject/Project/License.aspx *
 ***********************************************************/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Globalization;
using System.Xml.XPath;
using DaveSexton.DocProject.Sandcastle.BuildComponents.TypeConverters.BuiltIn;
using System.Xml;

namespace DaveSexton.DocProject.Sandcastle.BuildComponents.Editors.BuiltIn
{
	internal sealed partial class ResolveReferenceLinksComponent2EditorDialog : DaveSexton.DocProject.Sandcastle.BuildComponents.Editors.CancelableBaseEditorDialog
	{
		#region Public Properties
		#endregion

		#region Private / Protected
		#endregion

		#region Constructors
		/// <summary>
		/// Constructs a new instance of the <see cref="ResolveReferenceLinksComponent2EditorDialog" /> class.
		/// </summary>
		public ResolveReferenceLinksComponent2EditorDialog()
		{
			InitializeComponent();

			localeComboBox.BeginUpdate();
			try
			{
				foreach (CultureInfo culture in CultureInfo.GetCultures(System.Globalization.CultureTypes.AllCultures))
					if (culture != CultureInfo.InvariantCulture)
						localeComboBox.Items.Add(culture.ToString());
			}
			finally
			{
				localeComboBox.EndUpdate();
			}

			foreach (int linkType in Enum.GetValues(typeof(ReferenceLinkType)))
				linkTypeColumn.Items.Add((ReferenceLinkType) linkType);
		}
		#endregion

		#region Methods
		protected override void UpdateForBuildComponent(SandcastleBuildComponent component)
		{
			XPathNavigator navigator = component.CreateNavigator();

			SuspendLayout();

			try
			{
				localeComboBox.SelectedIndex = -1;
				linkTargetComboBox.SelectedIndex = -1;

				string locale = navigator.GetAttribute("locale", "");
				string linkTarget = navigator.GetAttribute("linkTarget", "");

				if (locale != null && locale.Length == 0)
					locale = "en-US";

				try
				{
					CultureInfo culture = CultureInfo.GetCultureInfo(locale);
					localeComboBox.SelectedItem = culture.ToString();
				}
				catch (ArgumentException)
				{
					if ((locale = locale.Trim()).Length > 0)
					{
						localeComboBox.Items.Add(locale);
						localeComboBox.SelectedItem = locale;
					}
				}

				if (localeComboBox.SelectedIndex == -1)
					localeComboBox.SelectedItem = CultureInfo.GetCultureInfo("en-US").ToString();

				linkTargetComboBox.SelectedItem = linkTarget.Trim();

				if (linkTargetComboBox.Text.Length == 0)
					linkTargetComboBox.SelectedItem = "_blank";

				targetsBindingSource.DataSource = CreateTargetsDataTable(navigator);
			}
			finally
			{
				ResumeLayout();
			}
		}

		private DataTable CreateTargetsDataTable(IXPathNavigable component)
		{
			DataTable table = new DataTable();
			table.Locale = System.Globalization.CultureInfo.CurrentCulture;

			DataColumn column = table.Columns.Add("base", typeof(string));
			column.AllowDBNull = false;
			column.DefaultValue = string.Empty;

			column = table.Columns.Add("recurse", typeof(bool));
			column.AllowDBNull = false;
			column.DefaultValue = "False";

			column = table.Columns.Add("files", typeof(string));
			column.AllowDBNull = false;
			column.DefaultValue = string.Empty;

			column = table.Columns.Add("type", typeof(ReferenceLinkType));
			column.AllowDBNull = false;

			HelpTypes helpTypes = BuildComponent.ConfigurationHelpTypes;

			column.DefaultValue = ((helpTypes & HelpTypes.Help1x) != 0)
				? ReferenceLinkType.Local
				: ((helpTypes & HelpTypes.Help2x) != 0)
					? ReferenceLinkType.Index
					: ReferenceLinkType.None;

			FillTargetsDataTable(component, table);

			return table;
		}

		public static void FillTargetsDataTable(IXPathNavigable component, DataTable table)
		{
			XPathNavigator navigator = component.CreateNavigator();

			foreach (XPathNavigator child in navigator.SelectChildren("targets", ""))
			{
				DataRow row = table.NewRow();

				foreach (DataColumn column in table.Columns)
				{
					string value = child.GetAttribute(column.ColumnName, "");

					if (value != null && (value = value.Trim()).Length > 0)
					{
						if (column.DataType.IsSubclassOf(typeof(Enum)))
							row[column] = Enum.Parse(column.DataType, value, true);
						else
							row[column] = Convert.ChangeType(value, column.DataType, System.Globalization.CultureInfo.CurrentCulture);
					}
				}

				table.Rows.Add(row);
			}
		}

		private void SaveAttributes()
		{
			XPathNavigator navigator = BuildComponent.CreateNavigator();

			string linkTarget = linkTargetComboBox.Text;

			if (!string.IsNullOrEmpty(linkTarget) && !string.Equals(linkTarget, "_blank", StringComparison.OrdinalIgnoreCase))
			{
				XPathNavigator clone = navigator.Clone();

				if (clone.MoveToAttribute("linkTarget", ""))
					clone.SetValue(linkTarget);
				else
					clone.CreateAttribute(null, "linkTarget", null, linkTarget);
			}

			string locale = localeComboBox.Text;

			if (!string.IsNullOrEmpty(locale) && !string.Equals(locale, "en-US", StringComparison.OrdinalIgnoreCase))
			{
				XPathNavigator clone = navigator.Clone();

				if (clone.MoveToAttribute("locale", ""))
					clone.SetValue(locale);
				else
					clone.CreateAttribute(null, "locale", null, locale);
			}
		}

		public static void SaveTargetsDataTable(IXPathNavigable component, DataTable table)
		{
			if (component == null)
				throw new ArgumentNullException("component");

			if (table == null)
				throw new ArgumentNullException("table");

			XPathNavigator navigator = component.CreateNavigator();

			StringBuilder output = new StringBuilder(Math.Max(navigator.InnerXml.Length, 256));

			XmlWriterSettings settings = new XmlWriterSettings();
			settings.ConformanceLevel = ConformanceLevel.Fragment;
			settings.Indent = true;

			using (XmlWriter writer = XmlWriter.Create(output, settings))
			{
				foreach (DataRow row in table.Rows)
				{
					writer.WriteStartElement("targets");

					foreach (DataColumn column in table.Columns)
					{
						string value;

						// NOTE: enum is checked first since the link type column's value must always be written, even if it's equal to the default value (which is verified afterwards)
						if (column.DataType.IsSubclassOf(typeof(Enum)))
							value = Enum.Parse(column.DataType, row[column].ToString(), false).ToString();
						else if (row[column].Equals(column.DefaultValue))
							value = null;
						else if (column.DataType == typeof(string))
							value = (string) row[column];
						else
							value = Convert.ToString(row[column], System.Globalization.CultureInfo.CurrentCulture);

						if (value != null && (value = value.Trim()).Length > 0)
							writer.WriteAttributeString(column.ColumnName, value);
					}

					writer.WriteEndElement();
				}
			}

			navigator.InnerXml = output.ToString();
		}

		protected override bool SaveChanges()
		{
			if (!ValidateChildren())
				return false;

			DataTable table = targetsBindingSource.DataSource as DataTable;

			if (table != null)
			{
				SaveAttributes();
				SaveTargetsDataTable(BuildComponent, table);
			}

			return true;
		}
		#endregion

		#region Event Handlers
		private void targetsDataGrid_DataError(object sender, DataGridViewDataErrorEventArgs e)
		{
			e.Cancel = true;
		}
		#endregion
	}
}